home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.mactech.com 2010
/
ftp.mactech.com.tar
/
ftp.mactech.com
/
machack
/
Hacks97
/
ContextWarrior.sit
/
ContextWarrior
/
source code
/
ContextWarrior.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-06-28
|
10KB
|
388 lines
// ContextWarrior
// MacHack 97
// Graham Herrick
// this file is public domain
#include <SetUpA4.h>
#include <A4Stuff.h>
#include <AppleGuide.h>
#include <Speech.h>
#include "ContextualMenu.h"
#include "MoreFilesExtras.h"
#define kInitID 128
#define kCWFileMenuID 0x81
#define kCWEditMenuID 0x82
#define kCWSearchMenuID 0x83
#define kCWProjectMenuID 0x85
#define kCWWindowMenuID 0x84
#define kCWHelpMenuID 0xBF96
enum
{
kNowhere, // this goes to file menu
kProjWindowContent, // map this to project menu
kNormWindowContent, // map this to edit menu?
kToolWindowContent, // this goes to search menu
kWindowStructure // map this to window menu and/or file menu
};
typedef pascal void (*IMType)(void);
typedef pascal long (*MSType)(Point pt);
typedef struct
{
MenuHandle menuoH;
short menuLeft;
} MenuRec;
typedef struct
{
short lastMenu,
lastRight,
mbResID;
MenuRec menus[];
} MenuList, *MenuListPtr, **MenuListHdl;
void *gOldJGNE;
IMType gOldInitMenus;
MSType gOldMenuSelect;
Boolean inJGNE;
Boolean fakingAThing;
Boolean hasCM,cmChecked,hasSpeech,speechChecked;
long fakeResult;
short oldMenuID;
FSSpec gFileSpec;
short helpStage;
Str255 helpMess;
pascal asm void myJGNE(void);
pascal asm void NewInitMenusShell(void);
pascal asm long NewMenuSelectShell(Point pt);
long NewMenuSelect(Point pt);
Boolean myGNE(EventRecord *event, Boolean preResult);
MenuHandle GetCopyOfMenuWithThisID(short id, short newID);
void NewInitMenus(void);
Boolean ThisIsCodeWarrior(void);
short WhereIsTheMouse(Point pt);
void pStrCopy(StringPtr p1, StringPtr p2);
void main(void)
{
long oldA4;
Handle theInit = 0L;
OSErr myErr;
long result;
oldA4 = SetCurrentA4();
RememberA4();
myErr = Gestalt(gestaltSystemVersion,&result);
if(myErr || (LoWord(result) < 0x0800)) goto fail;
theInit = Get1Resource('INIT',kInitID);
if(!theInit) goto fail;
fakingAThing = inJGNE = hasCM = cmChecked = hasSpeech = speechChecked = false;
helpStage = 0;
gFileSpec.name[0] = 0;
gOldJGNE = LMGetGNEFilter();
gOldInitMenus = (IMType)GetToolTrapAddress(_InitMenus);
gOldMenuSelect = (MSType)GetToolTrapAddress(_MenuSelect);
LMSetGNEFilter(myJGNE);
SetToolTrapAddress((UniversalProcPtr)NewInitMenusShell,_InitMenus);
SetToolTrapAddress((UniversalProcPtr)NewMenuSelectShell,_MenuSelect);
DetachResource(theInit);
goto exit;
fail:
SysBeep(10);
SysBeep(10);
SysBeep(10);
if(theInit) ReleaseResource(theInit);
exit:
RestoreA4(oldA4);
}
pascal asm long NewMenuSelectShell(Point pt)
{
movem.l a0-a3/a6-a7/d0-d7,-(sp)
JSR SetUpA4
MOVE.L D0,D3 // res(4),pt(4),rtn(4),reg(38)
MOVE.L 0x003C(sp),-(sp) // res(4),pt(4),rtn(4),reg(38),pt(4)
JSR NewMenuSelect
MOVE.L D0,d2 // res(4),pt(4),rtn(4),reg(38),pt(4)
MOVE.L d3,D0
EXG D0,A4
addq.w #4,sp
MOVE.L d2,0x0040(sp) // res(4),pt(4),rtn(4),reg(38)
movem.l (sp)+,a0-a3/a6-a7/d0-d7 // res(4),pt(4),rtn(4)
RTD #4
}
long NewMenuSelect(Point pt)
{
long result;
if(ThisIsCodeWarrior() && fakingAThing && pt.v == 10 && pt.v == 10)
{
fakingAThing = false;
result = fakeResult;
}
else result = gOldMenuSelect(pt);
return result;
}
void NewInitMenus(void)
{
if (ThisIsCodeWarrior())
{
OSErr myErr;
short mwRefNum = CurResFile();
FSSpec dirSpec, gdirSpec;
long gdparID;
Boolean isDir;
if(!speechChecked)
{
myErr = Gestalt(gestaltSpeechAttr,&gdparID);
if (!myErr && (gdparID & (1<<gestaltSpeechMgrPresent))) hasSpeech = true;
speechChecked = true;
}
if (!cmChecked)
{
myErr = Gestalt(gestaltContextualMenuAttr,&gdparID);
if (!myErr && (gdparID & (1<<gestaltContextualMenuTrapAvailable))) hasCM = true;
cmChecked = true;
}
if(hasCM)
{
InitContextualMenus();
helpStage = 0;
myErr = Gestalt(gestaltHelpMgrAttr,&gdparID);
if (!myErr && (gdparID & (1<<gestaltAppleGuidePresent)))
{
myErr = FSpGetFileLocation(mwRefNum,&dirSpec);
if(!myErr) myErr = FSMakeFSSpec(dirSpec.vRefNum,dirSpec.parID,
"\p(CodeWarrior Guides)",&gdirSpec);
if(!myErr) myErr = FSpGetDirectoryID(&gdirSpec,&gdparID,&isDir);
if(!myErr) myErr = FSMakeFSSpec(gdirSpec.vRefNum,gdparID,
"\pCodeWarrior IDE Guide",&gFileSpec);
}
}
}
}
pascal asm void NewInitMenusShell(void)
{
movem.l a0-a3/a6-a7/d0-d7,-(sp)
subq.w #4,sp
jsr SetUpA4
move.l d0,(sp)
jsr NewInitMenus
movea.l gOldInitMenus,a0
jsr (a0)
move.l (sp),d0
exg d0,a4
addq.w #4,sp
movem.l (sp)+,a0-a3/a6-a7/d0-d7
rts
}
pascal asm void myJGNE(void)
{
MOVE.L D0,A0 // save pre-result from SetUpA4
JSR SetUpA4 // fix A4, stomp D0
MOVE.L D0,-(A7) // save old A4
MOVE.L A0,D0 // restore pre-result
TST.B inJGNE // is myJGNE busy?
BNE @1 // yes, so bail
MOVE.B #true,inJGNE // mark myJGNE busy
MOVE.W D0,-(A7) // push pre-result
MOVE.L A1,-(A7) // push event record pointer
JSR myGNE // do the real work
MOVE.L (A7)+,A1 // restore event record pointer
ADDQ.L #2,A7 // pop pre-result; post-result in D0
ASL.W #8,D0 // bump C boolean to Lisa
MOVE.W D0,8(A7) // stash result where caller expects it
MOVE.B #false,inJGNE // mark myJGNE not busy
@1:
MOVE.L gOldJGNE,A0 // get previous jGNE
MOVE.L (A7)+,A4 // restore A4
cmp.l #0,a0
beq bail
MOVE.L A0,-(A7) // return to previous jGNE
bail:
RTS
}
Boolean myGNE(EventRecord *event, Boolean preResult)
{
Boolean postResult = preResult;
if (preResult)
{
if (event->what == mouseDown || event->what == mouseUp && ThisIsCodeWarrior() &&
cmChecked && hasCM)
{
if(IsShowContextualMenuClick(event))
{
MenuHandle fileMenu;
short theID, place = WhereIsTheMouse(event->where);
switch(place)
{
case kProjWindowContent: theID = kCWProjectMenuID; break;
case kNormWindowContent: theID = kCWEditMenuID; break;
case kWindowStructure: theID = kCWWindowMenuID; break;
case kToolWindowContent: theID = kCWSearchMenuID; break;
case kNowhere:
default: theID = kCWFileMenuID; break;
}
fileMenu = GetCopyOfMenuWithThisID(theID,theID+5678);
if(fileMenu)
{
unsigned long selType;
short selMenuID;
unsigned short selMenuItem;
OSErr myErr;
InsertMenu(fileMenu,hierMenu);
if(helpStage>0 && helpStage<4)
myErr = ContextualMenuSelect(fileMenu,event->where,false,
kCMHelpItemOtherHelp,helpMess,0L,&selType,
&selMenuID,&selMenuItem);
else
myErr = ContextualMenuSelect(fileMenu,event->where,false,
kCMHelpItemAppleGuide,"\p",0L,&selType,
&selMenuID,&selMenuItem);
DeleteMenu(theID+5678);
DisposeHandle((Handle)fileMenu);
if (selMenuID==theID+5678) selMenuID = theID;
if (!myErr && selType == kCMMenuItemSelected)
{
fakeResult = ((long)selMenuID << 16) & 0xFFFF0000;
fakeResult |= (selMenuItem & 0x0000FFFF);
fakingAThing = true;
// should find a better way to put mouse in menu bar
event->where.h = event->where.v = 10;
}
else if (!myErr && selType == kCMShowHelpSelected)
{
AGRefNum agRes;
if(helpStage==0)
{
helpStage=1;
pStrCopy("\pReal warriors don't need help",helpMess);
if (hasSpeech) SpeakString(helpMess);
}
else if (helpStage==1)
{
helpStage++;
pStrCopy("\pMaybe you're a virtual warrior",helpMess);
if (hasSpeech) SpeakString(helpMess);
}
else if (helpStage==2)
{
helpStage++;
pStrCopy("\pOr a CodePeacenik™",helpMess);
if (hasSpeech) SpeakString(helpMess);
}
else if (helpStage==3)
{
helpStage++;
pStrCopy("\pOkay. Here's some help.",helpMess);
if (hasSpeech) SpeakString(helpMess);
if (gFileSpec.name[0]) goto thing;
}
else if (gFileSpec.name[0])
{
thing:
helpStage++;
if(helpStage>15) helpStage = 0;
switch(place)
{
case kProjWindowContent:
myErr = AGOpenWithSearch(&gFileSpec,0,nil,"\pprojects",&agRes);
break;
case kWindowStructure:
myErr = AGOpenWithSearch(&gFileSpec,0,nil,"\pcredits",&agRes);
break;
case kToolWindowContent:
myErr = AGOpenWithSearch(&gFileSpec,0,nil,"\ptoolbar",&agRes);
break;
case kNormWindowContent:
case kNowhere:
default:
myErr = AGOpenWithView(&gFileSpec,0,nil,kAGViewTopicAreas,&agRes);
break;
}
}
event->what = nullEvent;
postResult = false;
}
else postResult = false;
}
}
}
}
return postResult;
}
MenuHandle GetCopyOfMenuWithThisID(short id, short newID)
{
MenuListHdl theMList = (MenuListHdl)LMGetMenuList();
short numMenus,i;
MenuHandle aMenu;
if(!theMList || !*theMList) return 0L;
numMenus = (*theMList)->lastMenu/6;
for(i=0;i<numMenus;i++)
{
aMenu = (*theMList)->menus[i].menuoH;
if (aMenu && HandleZone((Handle)aMenu) && !MemError() && *aMenu && (*aMenu)->menuID == id)
{
HandToHand(&((Handle)aMenu));
(*aMenu)->menuID = newID;
return aMenu;
}
}
return 0L;
}
Boolean ThisIsCodeWarrior(void)
{
return EqualString(LMGetCurApName(),"\pCodeWarrior IDE 2.0",true,true);
}
short WhereIsTheMouse(Point pt)
{
WindowPeek frontWind = (WindowPeek)LMGetWindowList();
while(frontWind)
{
if(PtInRgn(pt,frontWind->strucRgn))
{
if(PtInRgn(pt,frontWind->contRgn))
{
Str255 title;
if(frontWind->windowKind==0x4E21)
return kNormWindowContent;
GetWTitle((WindowPtr)frontWind,title);
if(EqualString("\pToolbar",title,true,true))
return kToolWindowContent;
return kProjWindowContent;
}
return kWindowStructure;
}
frontWind = frontWind->nextWindow;
}
return kNowhere;
}
void pStrCopy(StringPtr p1, StringPtr p2)
{
BlockMoveData((Ptr)p1,(Ptr)p2,*p1+1);
}